我正在尝试将数组切成三组.我希望在开头有余数([1, 2]
在下面的例子中).
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] ... #=> [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
有一个很好的方法来做到这一点?
拆分数组的通常方法是:
arr.each_slice(3) # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]
这样就[10, 11]
可以在最后得到余数.我尝试如下,思考each_slice
可能会接受一个负面的论点并将其读作在数组中向后移动.
arr.each_slice(-3)
唉,它没用.
虽然有人可能会将数组反转三次,但实现目标的方法更为有效:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] a = arr.dup # not to modify it inplace [a.shift(a.size % 3)] + a.each_slice(3).to_a #? [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
BTW,arr.each_slice(3)
返回一个枚举器,而不是你在问题中发布的数组.
如Cary Swoveland所建议的更新或无效dup
:
n = a.size % 3 [a[0...n]] + a[n..-1].each_slice(3).to_a
UPD摆脱dup
由@sawa:
[a.first(a.size % 3)] + a.drop(a.size % 3).each_slice(3).to_a
UPD只是出于好奇(假设输入没有nil
元素):
([nil] * (3 - a.size % 3) + a).each_slice(3).to_a.tap do |a| a.unshift(a.shift.compact!) end
以上可能安全地在原始数组上运行,它不会在原地修改它.
正如Stefan在评论中所指出的UPD2,如果数组可以被3整除,上面的任何一个都会产生一个初始的空切片.所以,正确的解决方案(和,最快的,顺便说一句)应该是这样的:
(arr.size % 3).zero? ? arr.each_slice(3).to_a : ANY_OF_THE_ABOVE
一个简单的组合reverse
和each_slice
将要做的诀窍:
arr.reverse.each_slice(3).map(&:reverse).reverse #=> [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
说明:
我正在逆转阵列并做each_slice
.这会给我:
[[11, 10, 9], [8, 7, 6], [5, 4, 3], [2, 1]]
现在我正在迭代这个并反转每个子数组以匹配预期的子数组序列.map(&:reverse)
.最后我正在反转整个数组以获得所需的序列(最后一个.reverse
).